home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1996 #1 / Amiga Plus CD - 1996 - No. 1.iso / pd / netz / xbtx_v1.1 / gfxdisplay.cpp < prev    next >
C/C++ Source or Header  |  1995-09-26  |  31KB  |  1,423 lines

  1. /*
  2. **    $Id: GfxDisplay.cpp 1.4 1995/09/26 19:45:11 olsen Exp olsen $
  3. **
  4. **    :ts=4
  5. */
  6.  
  7. /*
  8.  * Amiga changes copyright © 1995 by Olaf Barthel, All Rights Reserved
  9.  *
  10.  * Copyright (c) 1992, 1993 Arno Augustin, Frank Hoering, University of
  11.  * Erlangen-Nuremberg, Germany.
  12.  * All rights reserved.
  13.  *
  14.  * Redistribution and use in source and binary forms, with or without
  15.  * modification, are permitted provided that the following conditions
  16.  * are met:
  17.  * 1. Redistributions of source code must retain the above copyright
  18.  *    notice, this list of conditions and the following disclaimer.
  19.  * 2. Redistributions in binary form must reproduce the above copyright
  20.  *    notice, this list of conditions and the following disclaimer in the
  21.  *    documentation and/or other materials provided with the distribution.
  22.  * 3. All advertising materials mentioning features or use of this software
  23.  *    must display the following acknowledgement:
  24.  *    This product includes software developed by the University of
  25.  *    Erlangen-Nuremberg, Germany.
  26.  * 4. Neither the name of the University nor the names of its contributors
  27.  *    may be used to endorse or promote products derived from this software
  28.  *    without specific prior written permission.
  29.  *
  30.  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
  31.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  32.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
  33.  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  34.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  36.  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  37.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  38.  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  39.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  40.  *
  41.  * This software has not been validated by the ``Bundesamt fuer Zulassungen in
  42.  * der Telekommunikation'' of the ``Deutsche Bundepost Telekom'' and thus
  43.  * must not be used for accessing the BTX-Network of the Telekom in Germany.
  44.  *
  45.  * Diese Software hat keine Zulassung durch das Bundesamt fuer Zulassungen in
  46.  * der Telekommunikation der Deutschen Bundespost Telekom und darf daher nicht
  47.  * am Netz der Deutschen Bundespost Telekom in Deutschland betrieben werden.
  48.  */
  49.  
  50. #include "GfxDisplay.hpp"
  51. #include "Attributes.h"
  52. #include "RawKeys.h"
  53.  
  54. /****************************************************************************/
  55.  
  56. #include <graphics/modeid.h>
  57. #include <hardware/blit.h>
  58. #include <exec/execbase.h>
  59.  
  60. #include <clib/intuition_protos.h>
  61. #include <clib/graphics_protos.h>
  62. #include <clib/utility_protos.h>
  63. #include <clib/keymap_protos.h>
  64. #include <clib/exec_protos.h>
  65. #include <clib/dos_protos.h>
  66.  
  67. #ifdef __SASC
  68. #include <pragmas/intuition_pragmas.h>
  69. #include <pragmas/graphics_pragmas.h>
  70. #include <pragmas/utility_pragmas.h>
  71. #include <pragmas/keymap_pragmas.h>
  72. #include <pragmas/exec_pragmas.h>
  73. #include <pragmas/dos_pragmas.h>
  74.  
  75. extern struct IntuitionBase *IntuitionBase;
  76. extern struct GfxBase        *GfxBase;
  77. extern struct ExecBase        *SysBase;
  78. extern struct DosLibrary    *DOSBase;
  79. extern struct Library        *KeymapBase;
  80. extern struct Library        *UtilityBase;
  81. #endif    // __SASC
  82.  
  83. #include <string.h>
  84. #include <stdio.h>
  85.  
  86. /****************************************************************************/
  87.  
  88. #define SPREAD(v) ((((ULONG)v) << 24) | (((ULONG)v) << 16) | (((ULONG)v) << 8) | ((ULONG)v))
  89.  
  90. GfxDisplay::GfxDisplay()
  91. {
  92.     WORD i;
  93.  
  94.     Screen    = NULL;
  95.     Window    = NULL;
  96.  
  97.     for(i = 0 ; i < 60 ; i++)
  98.         Pen[i] = -1;
  99.  
  100.     WaitingChar = -1;
  101.  
  102.     memset(&LocalBitMap,0,sizeof(LocalBitMap));
  103.     memset(btx_font,0,sizeof(btx_font));
  104.     memset(fullrow_bg,0,sizeof(fullrow_bg));
  105.     cur_fg = -1;
  106.     cur_bg = -1;
  107. }
  108.  
  109. GfxDisplay::~GfxDisplay()
  110. {
  111.     Close();
  112. }
  113.  
  114. VOID GfxDisplay::Close(VOID)
  115. {
  116.     free_DRCS();
  117.     free_font_pixmaps();
  118.  
  119.     FreeVec(LocalBitMap.Planes[0]);
  120.  
  121.     if(Window)
  122.     {
  123.         EraseRect(RPort,Window->BorderLeft,Window->BorderTop,Window->Width - (Window->BorderRight+1),Window->Height - (Window->BorderBottom+1));
  124.  
  125.         ReleaseColours();
  126.  
  127.         CloseWindow(Window);
  128.  
  129.         Window = NULL;
  130.     }
  131.  
  132.     ReleaseColours();
  133.  
  134.     if(Screen)
  135.     {
  136.         CloseScreen(Screen);
  137.  
  138.         Screen = NULL;
  139.     }
  140. }
  141.  
  142. VOID GfxDisplay::MonitorData(int *btx_rows,int *btx_fontheight)
  143. {
  144.     rows        = btx_rows;
  145.     fontheight    = btx_fontheight;
  146. }
  147.  
  148. LONG GfxDisplay::Open(STRPTR PubScreenName,int XScale,int YScale,BOOL Direct)
  149. {
  150.     struct Screen *PubScreen;
  151.  
  152.     DirectRender = Direct;
  153.  
  154.     if(XScale < 1)
  155.         XScale = 1;
  156.  
  157.     if(YScale < 1)
  158.         YScale = 1;
  159.  
  160.     if(XScale > MAX_ZOOM)
  161.         XScale = MAX_ZOOM;
  162.  
  163.     if(XScale > MAX_ZOOM)
  164.         XScale = MAX_ZOOM;
  165.  
  166.     if(PubScreen = LockPubScreen((UBYTE *)PubScreenName))
  167.     {
  168.         VPort = &PubScreen -> ViewPort;
  169.  
  170.         if(InitColours())
  171.         {
  172.             for(;;)
  173.             {
  174.                 if(Window = OpenWindowTags(NULL,
  175.                     WA_PubScreen,        PubScreen,
  176.                     WA_InnerWidth,        40 * FONT_WIDTH        * XScale,
  177.                     WA_InnerHeight,        20 * FONT_HEIGHT    * YScale,
  178.                     WA_RMBTrap,         TRUE,
  179.                     WA_IDCMP,            IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_CLOSEWINDOW,
  180.                     WA_DepthGadget,        TRUE,
  181.                     WA_CloseGadget,        TRUE,
  182.                     WA_DragBar,            TRUE,
  183.                     WA_Title,            "xBTX",
  184.                     WA_AutoAdjust,        FALSE,
  185.                 TAG_DONE))
  186.                     break;
  187.                 else
  188.                 {
  189.                     if(YScale > 1)
  190.                     {
  191.                         YScale = (YScale + 1) / 2;
  192.                         continue;
  193.                     }
  194.  
  195.                     if(XScale > 1)
  196.                     {
  197.                         XScale = (XScale + 1) / 2;
  198.                         continue;
  199.                     }
  200.  
  201.                     ReleaseColours();
  202.                     break;
  203.                 }
  204.             }
  205.         }
  206.  
  207.         UnlockPubScreen(NULL,PubScreen);
  208.     }
  209.  
  210.     if(!Window)
  211.     {
  212.         UWORD Pens = (UWORD)~0;
  213.         ULONG DisplayID;
  214.  
  215.         DisplayID = FindBestModeID(
  216.             BIDTAG_NominalWidth,    40 * FONT_WIDTH        * XScale,
  217.             BIDTAG_NominalHeight,    20 * FONT_HEIGHT    * YScale,
  218.             BIDTAG_Depth,            8,
  219.         TAG_DONE);
  220.  
  221.         if(DisplayID == INVALID_ID)
  222.             return(-1);
  223.  
  224.         if(Screen = OpenScreenTags(NULL,
  225.             SA_Depth,            8,
  226.             SA_DisplayID,        DisplayID,
  227.             SA_Overscan,        OSCAN_TEXT,
  228.             SA_SharePens,        TRUE,
  229.             SA_SysFont,         1,
  230.             SA_Interleaved,     TRUE,
  231.             SA_AutoScroll,        TRUE,
  232.             SA_Width,            40 * FONT_WIDTH        * XScale,
  233.             SA_Height,            20 * FONT_HEIGHT    * YScale,
  234.             SA_Pens,            &Pens,
  235.             SA_Quiet,            TRUE,
  236.             SA_ShowTitle,        FALSE,
  237.             SA_Behind,            TRUE,
  238.         TAG_DONE))
  239.         {
  240.             VPort = &Screen->ViewPort;
  241.  
  242.             if(InitColours())
  243.             {
  244.                 if(!(Window = OpenWindowTags(NULL,
  245.                     WA_CustomScreen,    Screen,
  246.                     WA_Width,            Screen->Width,
  247.                     WA_Height,            Screen->Height,
  248.                     WA_Backdrop,        TRUE,
  249.                     WA_Borderless,        TRUE,
  250.                     WA_RMBTrap,         TRUE,
  251.                     WA_IDCMP,            IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_CLOSEWINDOW,
  252.                 TAG_DONE)))
  253.                 {
  254.                     CloseWindow(Window);
  255.                     Window = NULL;
  256.  
  257.                     CloseScreen(Screen);
  258.                     Screen = NULL;
  259.                 }
  260.             }
  261.             else
  262.             {
  263.                 CloseScreen(Screen);
  264.                 Screen = NULL;
  265.             }
  266.         }
  267.     }
  268.  
  269.     if(Window)
  270.     {
  271.         RPort        = Window->RPort;
  272.         WindowPort    = Window->UserPort;
  273.         WindowMask    = 1UL << WindowPort->mp_SigBit;
  274.  
  275.         FgPen = 0;
  276.         BgPen = 0;
  277.  
  278.         SetABPenDrMd(RPort,Pen[FgPen],Pen[BgPen],JAM2);
  279.  
  280.         DisplayWidth    = (UWORD)(40 * FONT_WIDTH    * XScale);
  281.         DisplayHeight    = (UWORD)(20 * FONT_HEIGHT    * YScale);
  282.  
  283.         ScaleX            = XScale;
  284.         ScaleY            = YScale;
  285.  
  286.         InitBitMap(&LocalBitMap,8,2 * FONT_WIDTH * ScaleX,2 * FONT_HEIGHT * ScaleY);
  287.         InitRastPort(&LocalRPort);
  288.  
  289.         InitRastPort(&TempRPort);
  290.  
  291.         SetDrMd(&TempRPort,JAM1);
  292.  
  293.         if(LocalBitMap.Planes[0] = (PLANEPTR)AllocVec(LocalBitMap.Depth * LocalBitMap.BytesPerRow * LocalBitMap.Rows,MEMF_CHIP))
  294.         {
  295.             LONG PlaneSize = LocalBitMap.BytesPerRow * LocalBitMap.Rows;
  296.             WORD i;
  297.  
  298.             for(i = 1 ; i < LocalBitMap.Depth ; i++)
  299.                 LocalBitMap.Planes[i] = LocalBitMap.Planes[i - 1] + PlaneSize;
  300.  
  301.             LocalRPort.BitMap = &LocalBitMap;
  302.  
  303.             init_fonts();
  304.  
  305.             ScreenToFront(Window->WScreen);
  306.             ActivateWindow(Window);
  307.  
  308.             return(0);
  309.         }
  310.  
  311.         ReleaseColours();
  312.  
  313.         CloseWindow(Window);
  314.         Window = NULL;
  315.  
  316.         if(Screen)
  317.         {
  318.             CloseScreen(Screen);
  319.             Screen = NULL;
  320.         }
  321.     }
  322.  
  323.     return(-1);
  324. }
  325.  
  326. VOID GfxDisplay::PutLine(STRPTR Line)
  327. {
  328.     if(Line)
  329.     {
  330.         int i,bg,len;
  331.  
  332.         bg = 32+4+PutIndex;
  333.  
  334.         SetFgPen(bg);
  335.         Fill(0,PutIndex*(*fontheight)*ScaleY,DisplayWidth, (*fontheight)*ScaleY);
  336.  
  337.         if((len = (int)strlen(Line)) > 40)
  338.             len = 40;
  339.  
  340.         for(i = 0 ; i < len ; i++)
  341.             xputc(Line[i],0,i,PutIndex,0,0,0,0,7,bg);
  342.  
  343.         PutIndex = (WORD)((PutIndex + 1) % (*rows));
  344.     }
  345.     else
  346.     {
  347.         PutIndex = 0;
  348.         xclearscreen();
  349.     }
  350. }
  351.  
  352. void GfxDisplay::init_fonts()
  353. {
  354.    static UBYTE raw_del[] = { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
  355.                  0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
  356.                  0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f };
  357.  
  358.    extern UBYTE raw_font[];
  359.  
  360.    int n, i;
  361.  
  362.    /* primary graphic, 2nd suppl. mosaic, suppl. graphic, 3rd suppl. mosaic */
  363.    for(n=0; n<4*96; n++) {
  364.       btx_font[n].raw  = (UBYTE *)&raw_font[n*2*FONT_HEIGHT];
  365.       btx_font[n].bits = 1;
  366.       btx_font[n].link = NULL;
  367.       for(i=0; i<4; i++)  btx_font[n].map[i] = NULL;
  368.    }
  369.  
  370.    /* link chars into '1st supplementary mosaic' (L) set */
  371.    for(n=0; n<32; n++) {
  372.       btx_font[SUP1*96+n].link      = btx_font+SUP2*96+n;
  373.       btx_font[SUP1*96+n+32].link = btx_font+PRIM*96+n+32;
  374.       btx_font[SUP1*96+n+64].link = btx_font+SUP2*96+n+64;
  375.    }
  376.  
  377.    /* initialize the DEL character of the L set */
  378.    btx_font[L*96+0x7f-0x20].link = NULL;
  379.    btx_font[L*96+0x7f-0x20].raw = raw_del;
  380.    btx_font[L*96+0x7f-0x20].bits = 1;
  381.    for(i=0; i<4; i++)  btx_font[L*96+0x7f-0x20].map[i] = NULL;
  382.  
  383.    /* initialize DRCS font to all NULL's */
  384.    btx_font[DRCS*96+0].link = btx_font;    /* link 'SPACE' */
  385.    for(n=1; n<96; n++) {
  386.       btx_font[DRCS*96+n].bits = 0;
  387.       btx_font[DRCS*96+n].raw  = NULL;
  388.       btx_font[DRCS*96+n].link = NULL;
  389.       for(i=0; i<4; i++)  btx_font[DRCS*96+n].map[i] = NULL;
  390.    }
  391. }
  392.  
  393. void GfxDisplay::xputc(int c,int set,int x,int y,int xdouble,int ydouble,int underline,int diacrit,int fg,int bg)
  394. {
  395.    btxchar *ch, *dia;
  396.  
  397.    if(x<0 || y<0 || x>39 || y>(*rows)-1) return;
  398.  
  399.    ch = btx_font + set*96 + c - 0x20;
  400.  
  401.    /* folow the link pointer */
  402.    if(ch->link)  ch = ch->link;
  403.  
  404.    /* a yet undefined DRC should be drawn - draw a SPACE */
  405.    if(!ch->raw)  ch = btx_font;
  406.  
  407.    if(ch->bits==1) {
  408.       dia = diacrit ? &btx_font[SUPP*96 + diacrit - 0x20] : (btxchar *)NULL;
  409.       xdraw_normal_char(ch, x, y, xdouble, ydouble, underline, dia, fg, bg);
  410.    }
  411.    else {  /* 2/4 bits */
  412.       xdraw_multicolor_char(ch, x, y, xdouble, ydouble);
  413.    }
  414. }
  415.  
  416. void GfxDisplay::xdraw_normal_char(btxchar *ch,int x,int y,int xd,int yd,int ul,btxchar *dia,int fg,int bg)
  417. {
  418.    int size;
  419.  
  420.    if(fg==TRANSPARENT)    fg = 32+4+y;
  421.    if(bg==TRANSPARENT)    bg = 32+4+y;
  422.  
  423.    if(fg != cur_fg)
  424.    {
  425.        PreparePaintFg(fg);
  426.        PreparePaintFgBg(fg,bg);
  427.    }
  428.    else
  429.    {
  430.       if(bg != cur_bg)
  431.           PreparePaintFgBg(fg,bg);
  432.    }
  433.  
  434.    cur_fg = fg;
  435.    cur_bg = bg;
  436.  
  437.    size = yd*2 + xd;
  438.    /* Pixmap not available in this size, create it */
  439.    if(!ch->map[size])
  440.        ch->map[size] = rawfont2bitmap(ch->raw, (xd+1),(yd+1));
  441.  
  442.    if(dia && !dia->map[size])
  443.        dia->map[size] = rawfont2bitmap(dia->raw, (xd+1),(yd+1));
  444.  
  445.    if(ch->map[size])
  446.        DrawTemplate(ch->map[size],FgBgMinterms,x*FONT_WIDTH*ScaleX, y*(*fontheight)*ScaleY,FONT_WIDTH*ScaleX*(xd+1),(*fontheight)*ScaleY*(yd+1));
  447.  
  448.    if(dia && dia->map[size])
  449.        DrawTemplate(dia->map[size],FgMinterms,x*FONT_WIDTH*ScaleX, y*(*fontheight)*ScaleY,FONT_WIDTH*ScaleX*(xd+1),(*fontheight)*(yd+1)*ScaleY);
  450.  
  451.    if(ul)
  452.    {
  453.        SetFgPen(fg);
  454.        Fill(x*FONT_WIDTH*ScaleX,y*(*fontheight)*ScaleY+((*fontheight)-1)*(yd+1)*ScaleY,FONT_WIDTH*ScaleX*(xd+1),(yd+1)*ScaleY);
  455.    }
  456. }
  457.  
  458. void GfxDisplay::xdraw_multicolor_char(btxchar *ch,int x,int y,int xd,int yd)
  459. {
  460.     int size;
  461.  
  462.     size = yd*2 + xd;
  463.  
  464.     if(!ch->map[size])
  465.         ch->map[size] = createpixmapfromfont(ch->raw, (xd+1),(yd+1), ch->bits );
  466.  
  467.     if(ch->map[size])
  468.         DrawTemplate(ch->map[size],NULL,x*FONT_WIDTH*ScaleX, y*(*fontheight)*ScaleY,FONT_WIDTH*ScaleX*(xd+1),(*fontheight)*(yd+1)*ScaleY);
  469. }
  470.  
  471. void GfxDisplay::xclearscreen()
  472. {
  473.     int y, bg;
  474.  
  475.     for(y=0; y<(*rows); y++)
  476.     {
  477.         bg = 32+4+y;
  478.  
  479.         SetFgPen(bg);
  480.         Fill(0,y*(*fontheight)*ScaleY,DisplayWidth, (*fontheight)*ScaleY);
  481.     }
  482. }
  483.  
  484. void GfxDisplay::xcursor(int x,int y)
  485. {
  486.     Complement(x*FONT_WIDTH*ScaleX,y*(*fontheight)*ScaleY,FONT_WIDTH*ScaleX,(*fontheight)*ScaleY);
  487. }
  488.  
  489. struct BitMap * GfxDisplay::rawfont2bitmap(UBYTE *src, int xzoom, int yzoom)
  490. {
  491.     struct BitMap *Bits;
  492.  
  493.     if(Bits = NewBitMap(1,FONT_WIDTH*ScaleX * xzoom,FONT_HEIGHT * yzoom * ScaleY))
  494.     {
  495.         if(src)
  496.         {
  497.             struct RastPort *RPort = &TempRPort;
  498.             int              x,y;
  499.             UBYTE             pattern;
  500.  
  501.             RPort->BitMap = Bits;
  502.  
  503.             Bits->Depth = 1;
  504.             SetRast(RPort,0);
  505.             SetAPen(RPort,1);
  506.  
  507.             for(y = 0 ; y < FONT_HEIGHT * yzoom * ScaleY ; y++)
  508.             {
  509.                 pattern = src[2 * (y / (yzoom*ScaleY))];
  510.  
  511.                 for(x = 0 ; x < (FONT_WIDTH / 2) * (xzoom*ScaleX) ; x++)
  512.                 {
  513.                     if(pattern & (1 << (5 - (x / (xzoom*ScaleX)))))
  514.                         WritePixel(RPort,x,y);
  515.                 }
  516.  
  517.                 pattern = src[2 * (y / (yzoom*ScaleY)) + 1];
  518.  
  519.                 for(x = 0 ; x < (FONT_WIDTH / 2) * xzoom*ScaleX ; x++)
  520.                 {
  521.                     if(pattern & (1 << (5 - (x / (xzoom*ScaleX)))))
  522.                         WritePixel(RPort,x + (FONT_WIDTH / 2) * xzoom*ScaleX,y);
  523.                 }
  524.             }
  525.  
  526.             Bits->Depth = 8;
  527.         }
  528.     }
  529.  
  530.     return(Bits);
  531. }
  532.  
  533. struct BitMap * GfxDisplay::createpixmapfromfont(UBYTE *src,int xzoom,int yzoom,int bits)
  534. {
  535.     UBYTE *d = data;
  536.     int c,i,j,k,l,x,y,byteindex;
  537.     struct BitMap *Bits;
  538.  
  539.     if(Bits = NewBitMap(8,FONT_WIDTH*ScaleX * xzoom,FONT_HEIGHT * yzoom * ScaleY))
  540.     {
  541.         struct RastPort *RPort;
  542.         LONG LastPen = -1,ThisPen;
  543.  
  544.         RPort = &TempRPort;
  545.  
  546.         RPort->BitMap = Bits;
  547.  
  548.         SetRast(RPort,0);
  549.  
  550.         if(src)
  551.         {
  552.             for(y=0; y<FONT_HEIGHT; y++)
  553.             {
  554.                 byteindex = 0;
  555.  
  556.                 for(l=0; l<2; l++)
  557.                 {
  558.                     for(x=5; x>=0; x--)
  559.                     {
  560.                         for(c=0, k=0; k<bits; k++)
  561.                         {
  562.                             if(*(src+k*FONT_HEIGHT*2) & (1<<x) )
  563.                                 c |= 1<<k;
  564.                         }
  565.  
  566.                         for(j=0; j<xzoom*ScaleX; j++)
  567.                             row[byteindex++] = (UBYTE)(bits==4 ? c+16 : c+32);
  568.                     }
  569.  
  570.                     src++;
  571.                 }
  572.  
  573.                 for(j=0; j<(yzoom*ScaleY); j++)
  574.                 {
  575.                     for(i=0; i<byteindex; i++)
  576.                         *d++ = row[i];
  577.                 }
  578.             }
  579.  
  580.             d = data;
  581.  
  582.             for(y = 0 ; y < FONT_HEIGHT * yzoom * ScaleY ; y++)
  583.             {
  584.                 for(x = 0 ; x < FONT_WIDTH*ScaleX * xzoom ; x++)
  585.                 {
  586.                     ThisPen = Pen[*d++];
  587.  
  588.                     if(LastPen != ThisPen)
  589.                         SetAPen(RPort,LastPen = ThisPen);
  590.  
  591.                     WritePixel(RPort,x,y);
  592.                 }
  593.             }
  594.         }
  595.     }
  596.  
  597.     return(Bits);
  598. }
  599.  
  600. void GfxDisplay::define_raw_DRC(int c,UBYTE *data, int bits)
  601. {
  602.     struct btxchar *ch = btx_font + DRCS*96 + c - 0x20;
  603.     int n;
  604.  
  605.     if(ch->raw)
  606.         delete ch->raw;
  607.  
  608.     for(n=0; n<4; n++)
  609.     {
  610.         if(ch->map[n])
  611.         {
  612.             DisposeBitMap(ch->map[n]);
  613.             ch->map[n] = NULL;
  614.         }
  615.     }
  616.  
  617.     if(ch->raw = new UBYTE[2*FONT_HEIGHT*bits])
  618.     {
  619.         memset(ch->raw,0,2*FONT_HEIGHT*bits);
  620.  
  621.         ch->bits = (UBYTE)bits;
  622.  
  623.         for(n=0; n<2*FONT_HEIGHT*bits; n++)
  624.             ch->raw[n] = data[n];
  625.  
  626.         ch->link = NULL;
  627.     }
  628. }
  629.  
  630. void GfxDisplay::free_DRCS()
  631. {
  632.     int i, n;
  633.  
  634.     btx_font[DRCS*96+0].link = btx_font;    /* link 'SPACE' */
  635.  
  636.     for(n=DRCS*96+1; n<(DRCS+1)*96; n++)
  637.     {
  638.         if(btx_font[n].raw)
  639.         {
  640.             delete btx_font[n].raw;
  641.             btx_font[n].raw = NULL;
  642.         }
  643.         for(i=0; i<4; i++)
  644.         {
  645.             if(btx_font[n].map[i])
  646.             {
  647.                 DisposeBitMap(btx_font[n].map[i]);
  648.                 btx_font[n].map[i] = NULL;
  649.             }
  650.             btx_font[n].link = NULL;
  651.             btx_font[n].bits = 0;
  652.         }
  653.     }
  654. }
  655.  
  656. void GfxDisplay::free_font_pixmaps()
  657. {
  658.     int i, n;
  659.  
  660.     for(n=0; n<6*96; n++)
  661.     {
  662.         if(!btx_font[n].link)
  663.         {
  664.             for(i=0; i<4; i++)
  665.             {
  666.                 if(btx_font[n].map[i])
  667.                 {
  668.                     DisposeBitMap(btx_font[n].map[i]);
  669.                     btx_font[n].map[i] = NULL;
  670.                 }
  671.             }
  672.         }
  673.     }
  674. }
  675.  
  676. void GfxDisplay::default_colors()
  677. {
  678.     init_colormap();
  679.     store_colors();
  680. }
  681.  
  682. void GfxDisplay::store_colors()
  683. {
  684.     int n;
  685.  
  686. //    for(n = 0 ; n < 16 ; n++)
  687. //        SetColour(n,colormap[n].red,colormap[n].green,colormap[n].blue);
  688.  
  689.     for(n = 0 ; n < 8 ; n++)
  690.     {
  691.         SetColour(n + 16,colormap[n + 16].red,colormap[n + 16].green,colormap[n + 16].blue);    // clut 2
  692.         SetColour(n + 24,colormap[n + 24].red,colormap[n + 24].green,colormap[n + 24].blue);    // clut 3
  693.     }
  694.  
  695.     for(n = 0 ; n < 4 ; n++)    // dclut
  696.         SetColour(32 + n,colormap[32 + n].red,colormap[32 + n].green,colormap[32 + n].blue);
  697.  
  698.     for(n = 0 ; n < 24 ; n++)
  699.         SetColour(32 + 4 + n,colormap[32 + 4 + n].red,colormap[32 + 4 + n].green,colormap[32 + 4 + n].blue);
  700. }
  701.  
  702. void GfxDisplay::init_colormap()
  703. {
  704.    int n;
  705.  
  706.    /* clut 0 + clut 1 */
  707.    for(n=0; n<16; n++) {  /* page 112) */
  708.       if(n==8)    { colormap[n] = colormap[0]; continue; }
  709.       colormap[n].red    = (UBYTE)(((n&1)>0) ? ( ((n&8)==0) ? 0xff : 0x7f ) : 0);
  710.       colormap[n].green = (UBYTE)(((n&2)>0) ? ( ((n&8)==0) ? 0xff : 0x7f ) : 0);
  711.       colormap[n].blue    = (UBYTE)(((n&4)>0) ? ( ((n&8)==0) ? 0xff : 0x7f ) : 0);
  712.    }
  713.  
  714.    /* clut 2 + clut 3 */
  715.    for(n=0; n<8; n++) {
  716.       colormap[n+16].red   = colormap[n+24].red   = (UBYTE)(n&1 ? 0xff : 0);
  717.       colormap[n+16].green = colormap[n+24].green = (UBYTE)(n&2 ? 0xff : 0);
  718.       colormap[n+16].blue  = colormap[n+24].blue  = (UBYTE)(n&4 ? 0xff : 0);
  719.    }
  720.  
  721.    /* DCLUT */
  722.    for(n=0; n<4; n++) {
  723.       colormap[32+n].red   = colormap[n].red;
  724.       colormap[32+n].green = colormap[n].green;
  725.       colormap[32+n].blue  = colormap[n].blue;
  726.       dclut[n] = n;
  727.    }
  728.  
  729.    /* fullrow background (BLACK) */
  730.    for(n=0; n<24; n++) {
  731.       colormap[32+4+n].red     = colormap[0].red;
  732.       colormap[32+4+n].green = colormap[0].green;
  733.       colormap[32+4+n].blue  = colormap[0].blue;
  734.       fullrow_bg[n] = 0;
  735.    }
  736. }
  737.  
  738. void GfxDisplay::define_color(int index,int r,int g,int b)    // 4 bit pro Eintrag
  739. {
  740.     int i;
  741.  
  742.     r &= 15;
  743.     g &= 15;
  744.     b &= 15;
  745.  
  746.     r = (r << 4) | r;
  747.     g = (g << 4) | g;
  748.     b = (b << 4) | b;
  749.  
  750.     colormap[index].red   = (UBYTE)r;
  751.     colormap[index].green = (UBYTE)g;
  752.     colormap[index].blue  = (UBYTE)b;
  753.     SetColour(index,r,g,b);
  754.  
  755.     /* if DCLUT contains this color, change DCLUT color too */
  756.     for(i=0; i<4; i++)
  757.     {
  758.         if(dclut[i]==index)
  759.             define_DCLUT(i, index);
  760.     }
  761.  
  762.     /* if fullrow_bg contains this color, change fullrow color too */
  763.     for(i=0; i<24; i++)
  764.     {
  765.         if(fullrow_bg[i]==index)
  766.             define_fullrow_bg(i, index);
  767.     }
  768. }
  769.  
  770. void GfxDisplay::define_DCLUT(int entry,int index)
  771. {
  772.    dclut[entry] = index;
  773.    colormap[32+entry].red    = colormap[index].red;
  774.    colormap[32+entry].green = colormap[index].green;
  775.    colormap[32+entry].blue    = colormap[index].blue;
  776.  
  777.    SetColour(32 + entry,colormap[32 + entry].red,colormap[32 + entry].green,colormap[32 + entry].blue);
  778. }
  779.  
  780. void GfxDisplay::define_fullrow_bg(int row,int index)
  781. {
  782.    fullrow_bg[row] = index;
  783.    colormap[32+4+row].red    = colormap[index].red;
  784.    colormap[32+4+row].green = colormap[index].green;
  785.    colormap[32+4+row].blue    = colormap[index].blue;
  786.  
  787.    SetColour(32 + 4 + row,colormap[32 + 4 + row].red,colormap[32 + 4 + row].green,colormap[32 + 4 + row].blue);
  788. }
  789.  
  790. /******************************************************************************/
  791.  
  792. #define V0H0    (0)
  793. #define V0H1    (NANBC | ANBNC | NANBC | ANBC)
  794. #define V1H0    (NABNC | ABNC | NABC | ABC)
  795. #define V1H1    (NANBC | NANBNC | NABC | NABNC | ANBC | ANBNC | ABC | ABNC)
  796.  
  797. #define PAINT_a (NANBC | ANBC | NABNC | ABNC | NABC | ABC)
  798. #define PAINT_b (ANBC | NANBC)
  799.  
  800. VOID GfxDisplay::PreparePaintFgBg(UBYTE Fore,UBYTE Back,UBYTE *Minterms)
  801. {
  802.     UBYTE Mask,Term,i;
  803.  
  804.     if(!Minterms)
  805.         Minterms = FgBgMinterms;
  806.  
  807.     Fore = (UBYTE)Pen[Fore];
  808.     Back = (UBYTE)Pen[Back];
  809.  
  810.     for(i = 0 ; i < 8 ; i++)
  811.     {
  812.         Mask = (UBYTE)(1 << i);
  813.  
  814.         if(Fore & Mask)
  815.         {
  816.             if(Back & Mask)
  817.                 Term = V1H1;
  818.             else
  819.                 Term = V1H0;
  820.         }
  821.         else
  822.         {
  823.             if(Back & Mask)
  824.                 Term = V0H1;
  825.             else
  826.                 Term = V0H0;
  827.         }
  828.  
  829.         Minterms[i] = Term;
  830.     }
  831. }
  832.  
  833. VOID GfxDisplay::PreparePaintFg(UBYTE Fore,UBYTE *Minterms)
  834. {
  835.     UBYTE Mask,Term,i;
  836.  
  837.     if(!Minterms)
  838.         Minterms = FgMinterms;
  839.  
  840.     Fore = (UBYTE)Pen[Fore];
  841.  
  842.     for(i = 0 ; i < 8 ; i++)
  843.     {
  844.         Mask = (UBYTE)(1 << i);
  845.  
  846.         if(Fore & Mask)
  847.             Term = PAINT_a;
  848.         else
  849.             Term = PAINT_b;
  850.  
  851.         Minterms[i] = Term;
  852.     }
  853. }
  854.  
  855. VOID GfxDisplay::DrawTemplate(CONST struct BitMap *BitMap,CONST UBYTE *Minterms,UWORD Left,UWORD Top,UWORD Width,UWORD Height)
  856. {
  857.     Left    += Window->BorderLeft;
  858.     Top        += Window->BorderTop;
  859.  
  860.     if(Minterms)
  861.     {
  862.         if(DirectRender)
  863.         {
  864.             WORD i;
  865.  
  866.             for(i = 0 ; i < 8 ; i++)
  867.             {
  868.                 SetWriteMask(RPort,1 << i);
  869.                 BltBitMapRastPort((struct BitMap *)BitMap,0,0,RPort,Left,Top,Width,Height,Minterms[i]);
  870.             }
  871.  
  872.             SetWriteMask(RPort,~0);
  873.         }
  874.         else
  875.         {
  876.             WORD i;
  877.  
  878.             SetRast(&LocalRPort,0);
  879.  
  880.             ClipBlit(RPort,Left,Top,&LocalRPort,0,0,Width,Height,0xC0);
  881.  
  882.             for(i = 0 ; i < 8 ; i++)
  883.                 BltBitMap((struct BitMap *)BitMap,0,0,&LocalBitMap,0,0,Width,Height,Minterms[i],1 << i,NULL);
  884.  
  885.             BltBitMapRastPort(&LocalBitMap,0,0,RPort,Left,Top,Width,Height,0xC0);
  886.         }
  887.     }
  888.     else
  889.         BltBitMapRastPort((struct BitMap *)BitMap,0,0,RPort,Left,Top,Width,Height,0xC0);
  890. }
  891.  
  892. VOID GfxDisplay::DisposeBitMap(struct BitMap *Bits)
  893. {
  894.     if(Bits)
  895.     {
  896.         FreeVec(Bits->Planes[0]);
  897.  
  898.         FreeVec(Bits);
  899.     }
  900. }
  901.  
  902. struct BitMap * GfxDisplay::NewBitMap(WORD Depth,WORD Width,WORD Height)
  903. {
  904.     struct BitMap *Bits;
  905.  
  906.     if(Bits = (struct BitMap *)AllocVec(sizeof(struct BitMap),MEMF_ANY))
  907.     {
  908.         InitBitMap(Bits,8,Width,Height);
  909.  
  910.         if(Depth == 1)
  911.         {
  912.             if(Bits->Planes[0] = (PLANEPTR)AllocVec(Bits->BytesPerRow * Bits->Rows,MEMF_CHIP))
  913.             {
  914.                 WORD i;
  915.  
  916.                 for(i = 1 ; i < 8 ; i++)
  917.                     Bits->Planes[i] = Bits->Planes[0];
  918.             }
  919.         }
  920.         else
  921.         {
  922.             if(Bits->Planes[0] = (PLANEPTR)AllocVec(Depth * Bits->BytesPerRow * Bits->Rows,MEMF_CHIP))
  923.             {
  924.                 LONG PlaneSize = Bits->BytesPerRow * Bits->Rows;
  925.                 WORD i;
  926.  
  927.                 for(i = 1 ; i < Depth ; i++)
  928.                     Bits->Planes[i] = Bits->Planes[i - 1] + PlaneSize;
  929.             }
  930.         }
  931.  
  932.         if(Bits->Planes[0])
  933.             return(Bits);
  934.         else
  935.             FreeVec(Bits);
  936.     }
  937.  
  938.     return(NULL);
  939. }
  940.  
  941. VOID GfxDisplay::SetFgPen(LONG Index)
  942. {
  943.     if(Index != FgPen)
  944.     {
  945.         FgPen = Index;
  946.  
  947.         SetAPen(RPort,Pen[Index]);
  948.     }
  949. }
  950.  
  951. VOID GfxDisplay::SetBgPen(LONG Index)
  952. {
  953.     if(Index != BgPen)
  954.     {
  955.         BgPen = Index;
  956.  
  957.         SetBPen(RPort,Pen[Index]);
  958.     }
  959. }
  960.  
  961. VOID GfxDisplay::SetPens(LONG Fg,LONG Bg)
  962. {
  963.     if(Fg != FgPen || Bg != BgPen)
  964.     {
  965.         FgPen = Fg;
  966.         BgPen = Bg;
  967.  
  968.         SetABPenDrMd(RPort,Pen[Fg],Pen[Bg],JAM2);
  969.     }
  970. }
  971.  
  972. VOID GfxDisplay::Fill(LONG Left,LONG Top,LONG Width,LONG Height)
  973. {
  974.     if(Width > 0 && Height > 0)
  975.     {
  976.         Left    += Window->BorderLeft;
  977.         Top        += Window->BorderTop;
  978.  
  979.         RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
  980.     }
  981. }
  982.  
  983. VOID GfxDisplay::Complement(LONG Left,LONG Top,LONG Width,LONG Height)
  984. {
  985.     if(Width > 0 && Height > 0)
  986.     {
  987.         Left    += Window->BorderLeft;
  988.         Top        += Window->BorderTop;
  989.  
  990.         SetABPenDrMd(RPort,-1,0,JAM1 | COMPLEMENT);
  991.  
  992.         RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
  993.  
  994.         SetABPenDrMd(RPort,Pen[FgPen],Pen[BgPen],JAM2);
  995.     }
  996. }
  997.  
  998. VOID GfxDisplay::SetColour(LONG Index,UBYTE Red,UBYTE Green,UBYTE Blue)
  999. {
  1000.     ULONG Table[1 + 3 + 1];
  1001.  
  1002.     Table[0] = (1L << 16) | Pen[Index];
  1003.     Table[1] = SPREAD(Red);
  1004.     Table[2] = SPREAD(Green);
  1005.     Table[3] = SPREAD(Blue);
  1006.     Table[4] = 0;
  1007.  
  1008.     LoadRGB32(VPort,Table);
  1009. }
  1010.  
  1011. ULONG GfxDisplay::WaitMask(VOID)
  1012. {
  1013.     return(WindowMask);
  1014. }
  1015.  
  1016. LONG GfxDisplay::Waiting(VOID)
  1017. {
  1018.     if(WaitingChar == -1)
  1019.     {
  1020.         struct IntuiMessage *Message;
  1021.  
  1022.         while(Message = (struct IntuiMessage *)GetMsg(WindowPort))
  1023.         {
  1024.             if(Message->Class == IDCMP_RAWKEY)
  1025.             {
  1026.                 if((WaitingChar = (WORD)MapKey(Message)) >= 0)
  1027.                 {
  1028.                     ReplyMsg((struct Message *)Message);
  1029.  
  1030.                     return(1);
  1031.                 }
  1032.             }
  1033.             else
  1034.             {
  1035.                 if(Message->Class == IDCMP_CLOSEWINDOW)
  1036.                 {
  1037.                     ReplyMsg((struct Message *)Message);
  1038.  
  1039.                     WaitingChar = '\033';
  1040.  
  1041.                     return(1);
  1042.                 }
  1043.             }
  1044.  
  1045.             ReplyMsg((struct Message *)Message);
  1046.         }
  1047.  
  1048.         return(0);
  1049.     }
  1050.     else
  1051.         return(1);
  1052. }
  1053.  
  1054. LONG GfxDisplay::GetChar(VOID)
  1055. {
  1056.     if(WaitingChar == -1)
  1057.     {
  1058.         struct IntuiMessage *Message;
  1059.  
  1060.         while(Message = (struct IntuiMessage *)GetMsg(WindowPort))
  1061.         {
  1062.             if(Message->Class == IDCMP_RAWKEY)
  1063.             {
  1064.                 LONG Result = MapKey(Message);
  1065.  
  1066.                 ReplyMsg((struct Message *)Message);
  1067.  
  1068.                 return(Result);
  1069.             }
  1070.             else
  1071.             {
  1072.                 if(Message->Class == IDCMP_CLOSEWINDOW)
  1073.                 {
  1074.                     ReplyMsg((struct Message *)Message);
  1075.  
  1076.                     return('\033');
  1077.                 }
  1078.             }
  1079.  
  1080.             ReplyMsg((struct Message *)Message);
  1081.         }
  1082.  
  1083.         return(-1);
  1084.     }
  1085.     else
  1086.     {
  1087.         LONG Result = WaitingChar;
  1088.  
  1089.         WaitingChar = -1;
  1090.  
  1091.         return(Result);
  1092.     }
  1093. }
  1094.  
  1095. LONG GfxDisplay::MapKey(struct IntuiMessage *Message)
  1096. {
  1097.     static LONG Table[][2] =
  1098.     {
  1099.         RAWKEY_CursorUp,    KEY_CursorUp,
  1100.         RAWKEY_CursorDown,    KEY_CursorDown,
  1101.         RAWKEY_CursorRight, KEY_CursorRight,
  1102.         RAWKEY_CursorLeft,    KEY_CursorLeft,
  1103.  
  1104.         RAWKEY_Help,        KEY_Help,
  1105.  
  1106.         RAWKEY_F1,            -1,
  1107.         RAWKEY_F2,            -1,
  1108.         RAWKEY_F3,            -1,
  1109.         RAWKEY_F4,            -1,
  1110.         RAWKEY_F5,            -1,
  1111.         RAWKEY_F6,            -1,
  1112.         RAWKEY_F7,            -1,
  1113.         RAWKEY_F8,            -1,
  1114.         RAWKEY_F9,            -1,
  1115.         RAWKEY_F10,         -1,
  1116.  
  1117.         -1
  1118.     };
  1119.  
  1120.     UBYTE Buffer[10];
  1121.     WORD i;
  1122.  
  1123.     for(i = 0 ; Table[i][0] != -1 ; i++)
  1124.     {
  1125.         if((Message->Code & ~IECODE_UP_PREFIX) == Table[i][0])
  1126.         {
  1127.             if(Message->Code & IECODE_UP_PREFIX)
  1128.                 return(-1);
  1129.             else
  1130.                 return(Table[i][1]);
  1131.         }
  1132.     }
  1133.  
  1134.     Event.ie_Class        = IECLASS_RAWKEY;
  1135.     Event.ie_SubClass     = 0;
  1136.     Event.ie_Code         = Message->Code;
  1137.     Event.ie_Qualifier    = Message->Qualifier;
  1138.     Event.ie_EventAddress = (APTR *) *((ULONG *)Message->IAddress);
  1139.  
  1140.     Buffer[0] = 0;
  1141.  
  1142.     if(MapRawKey(&Event,(char *)&Buffer[0],10,(struct KeyMap *)NULL) > 0)
  1143.         return(Buffer[0]);
  1144.     else
  1145.         return(-1);
  1146. }
  1147.  
  1148. ULONG GfxDisplay::FindBestModeID(Tag FirstTag,...)
  1149. {
  1150.     struct TagItem            *List,
  1151.                             *Item;
  1152.     ULONG                     Mode;
  1153.  
  1154.     ULONG                     BestMode;
  1155.     LONG                     BestWidth,
  1156.                              BestHeight,
  1157.                              BestDepth;
  1158.  
  1159.     ULONG                     MustHave,
  1160.                              MustNotHave;
  1161.     ULONG                     MonitorID;
  1162.     struct ViewPort            *ViewPort;
  1163.     ULONG                     SourceID;
  1164.     UWORD                     NominalWidth,
  1165.                              NominalHeight;
  1166.     UWORD                     DesiredWidth,
  1167.                              DesiredHeight;
  1168.     UBYTE                     Depth;
  1169.  
  1170.     UBYTE                     RedBits;
  1171.     UBYTE                     BlueBits;
  1172.     UBYTE                     GreenBits;
  1173.  
  1174.     struct DisplayInfo         DisplayInfo;
  1175.     struct DimensionInfo     DimensionInfo;
  1176.  
  1177.     LONG                     Width,
  1178.                              Height;
  1179.  
  1180.     MustHave        = NULL;
  1181.     MustNotHave        = SPECIAL_FLAGS;
  1182.     Depth            = 1;
  1183.     MonitorID        = INVALID_ID;
  1184.     SourceID        = INVALID_ID;
  1185.     RedBits            = 4;
  1186.     BlueBits        = 4;
  1187.     GreenBits        = 4;
  1188.     NominalWidth    = 640,
  1189.     NominalHeight    = 200;
  1190.  
  1191.     List = (struct TagItem *)&FirstTag;
  1192.  
  1193.     while(Item = NextTagItem(&List))
  1194.     {
  1195.         switch(Item->ti_Tag)
  1196.         {
  1197.             case BIDTAG_DIPFMustHave:
  1198.  
  1199.                 MustHave = Item->ti_Data;
  1200.                 break;
  1201.  
  1202.             case BIDTAG_DIPFMustNotHave:
  1203.  
  1204.                 MustNotHave = Item->ti_Data;
  1205.                 break;
  1206.  
  1207.             case BIDTAG_RedBits:
  1208.  
  1209.                 RedBits = (UBYTE)Item->ti_Data;
  1210.                 break;
  1211.  
  1212.             case BIDTAG_GreenBits:
  1213.  
  1214.                 GreenBits = (UBYTE)Item->ti_Data;
  1215.                 break;
  1216.  
  1217.             case BIDTAG_BlueBits:
  1218.  
  1219.                 BlueBits = (UBYTE)Item->ti_Data;
  1220.                 break;
  1221.  
  1222.             case BIDTAG_MonitorID:
  1223.  
  1224.                 MonitorID = Item->ti_Data;
  1225.                 break;
  1226.  
  1227.             case BIDTAG_NominalWidth:
  1228.  
  1229.                 NominalWidth = (UWORD)Item->ti_Data;
  1230.                 break;
  1231.  
  1232.             case BIDTAG_NominalHeight:
  1233.  
  1234.                 NominalHeight = (UWORD)Item->ti_Data;
  1235.                 break;
  1236.         }
  1237.     }
  1238.  
  1239.     DesiredWidth    = NominalWidth;
  1240.     DesiredHeight    = NominalHeight;
  1241.  
  1242.     List = (struct TagItem *)&FirstTag;
  1243.  
  1244.     if(ViewPort = (struct ViewPort *)GetTagData(BIDTAG_ViewPort,NULL,List))
  1245.     {
  1246.         NominalWidth    = ViewPort->DWidth;
  1247.         NominalHeight    = ViewPort->DHeight;
  1248.         DesiredWidth    = NominalWidth;
  1249.         DesiredHeight    = NominalHeight;
  1250.         Depth            = ViewPort->RasInfo->BitMap->Depth;
  1251.         SourceID        = GetVPModeID(ViewPort);
  1252.     }
  1253.  
  1254.     if(Item = FindTagItem(BIDTAG_SourceID,List))
  1255.     {
  1256.         if(GetDisplayInfoData((APTR)NULL,(UBYTE *)&DisplayInfo,sizeof(DisplayInfo),DTAG_DISP,SourceID))
  1257.             MustHave = (DisplayInfo.PropertyFlags & SPECIAL_FLAGS) | MustHave;
  1258.         else
  1259.             return(INVALID_ID);
  1260.  
  1261.         if(GetDisplayInfoData((APTR)NULL,(UBYTE *)&DimensionInfo,sizeof(DimensionInfo),DTAG_DIMS,SourceID))
  1262.         {
  1263.             NominalWidth    = (UWORD)(DimensionInfo.Nominal.MaxX - DimensionInfo.Nominal.MinX + 1);
  1264.             NominalHeight    = (UWORD)(DimensionInfo.Nominal.MaxY - DimensionInfo.Nominal.MinY + 1);
  1265.             DesiredWidth    = NominalWidth;
  1266.             DesiredHeight    = NominalHeight;
  1267.         }
  1268.         else
  1269.             return(INVALID_ID);
  1270.     }
  1271.  
  1272.     List = (struct TagItem *)&FirstTag;
  1273.  
  1274.     while(Item = NextTagItem(&List))
  1275.     {
  1276.         switch(Item->ti_Tag)
  1277.         {
  1278.             case BIDTAG_DesiredWidth:
  1279.  
  1280.                 DesiredWidth = (UWORD)Item->ti_Data;
  1281.                 break;
  1282.  
  1283.             case BIDTAG_DesiredHeight:
  1284.  
  1285.                 DesiredHeight = (UWORD)Item->ti_Data;
  1286.                 break;
  1287.  
  1288.             case BIDTAG_Depth:
  1289.  
  1290.                 Depth = (UBYTE)Item->ti_Data;
  1291.                 break;
  1292.         }
  1293.     }
  1294.  
  1295.     BestMode    = INVALID_ID;
  1296.     BestWidth    = 0;
  1297.     BestHeight    = 0;
  1298.     BestDepth    = 0;
  1299.  
  1300.     Mode = INVALID_ID;
  1301.  
  1302.     while((Mode = NextDisplayInfo(Mode)) != INVALID_ID)
  1303.     {
  1304.         if(MonitorID != INVALID_ID)
  1305.         {
  1306.             if((Mode & MONITOR_ID_MASK) != MonitorID)
  1307.                 continue;
  1308.         }
  1309.  
  1310.         if(ModeNotAvailable(Mode) & ~DI_AVAIL_NOTWITHGENLOCK)
  1311.             continue;
  1312.  
  1313.         if(GetDisplayInfoData((APTR)NULL,(UBYTE *)&DisplayInfo,sizeof(DisplayInfo),DTAG_DISP,Mode) && GetDisplayInfoData((APTR)NULL,(UBYTE *)&DimensionInfo,sizeof(DimensionInfo),DTAG_DIMS,Mode))
  1314.         {
  1315.             if(DimensionInfo.MaxDepth < Depth || DisplayInfo.RedBits < RedBits || DisplayInfo.GreenBits < GreenBits || DisplayInfo.BlueBits < BlueBits)
  1316.                 continue;
  1317.  
  1318.             if(DimensionInfo.MaxDepth > 8 && Depth <= 8)
  1319.                 continue;
  1320.  
  1321.  
  1322.             if(MustHave)
  1323.             {
  1324.                 if((DisplayInfo.PropertyFlags & MustHave) != MustHave)
  1325.                     continue;
  1326.             }
  1327.  
  1328.             if(MustNotHave)
  1329.             {
  1330.                 if(DisplayInfo.PropertyFlags & MustNotHave)
  1331.                     continue;
  1332.             }
  1333.  
  1334.             Width    = DimensionInfo.TxtOScan.MaxX - DimensionInfo.TxtOScan.MinX + 1;
  1335.             Height    = DimensionInfo.TxtOScan.MaxY - DimensionInfo.TxtOScan.MinY + 1;
  1336.  
  1337.             if(DesiredWidth <= Width && DesiredHeight <= Height && NominalWidth <= DimensionInfo.Nominal.MaxX - DimensionInfo.Nominal.MinX + 1 && NominalHeight <= DimensionInfo.Nominal.MaxY - DimensionInfo.Nominal.MinY + 1)
  1338.             {
  1339.                 if(!BestWidth || !BestHeight || !BestDepth)
  1340.                 {
  1341.                     BestMode    = Mode;
  1342.                     BestDepth    = DimensionInfo.MaxDepth;
  1343.                     BestWidth    = DesiredWidth;
  1344.                     BestHeight    = DesiredHeight;
  1345.                 }
  1346.                 else
  1347.                 {
  1348.                     if(DimensionInfo.MaxDepth <= BestDepth && Width <= BestWidth && Height <= BestHeight)
  1349.                     {
  1350.                         BestMode    = Mode;
  1351.                         BestDepth    = DimensionInfo.MaxDepth;
  1352.                         BestWidth    = DesiredWidth;
  1353.                         BestHeight    = DesiredHeight;
  1354.                     }
  1355.                 }
  1356.             }
  1357.         }
  1358.     }
  1359.  
  1360.     return(BestMode);
  1361. }
  1362.  
  1363. VOID GfxDisplay::ReleaseColours(VOID)
  1364. {
  1365.     WORD i;
  1366.  
  1367.     for(i = 0 ; i < 60 ; i++)
  1368.     {
  1369.         if(Pen[i] != -1)
  1370.         {
  1371.             ReleasePen(VPort->ColorMap,Pen[i]);
  1372.  
  1373.             Pen[i] = -1;
  1374.         }
  1375.     }
  1376. }
  1377.  
  1378. BOOL GfxDisplay::InitColours(VOID)
  1379. {
  1380.     int n;
  1381.  
  1382.     init_colormap();
  1383.  
  1384.     for(n = 0 ; n < 16 ; n++)
  1385.     {
  1386.         Pen[n] = (LONG)ObtainBestPen(VPort->ColorMap,SPREAD(colormap[n].red),SPREAD(colormap[n].green),SPREAD(colormap[n].blue),
  1387.             OBP_Precision,    PRECISION_IMAGE,
  1388.             OBP_FailIfBad,    TRUE,
  1389.         TAG_DONE);
  1390.  
  1391.         if(Pen[n] == -1)
  1392.         {
  1393.             ReleaseColours();
  1394.             return(FALSE);
  1395.         }
  1396.     }
  1397.  
  1398.     for(n = 16 ; n < 60 ; n++)
  1399.     {
  1400.         Pen[n] = (LONG)ObtainPen(VPort->ColorMap,-1, 0,0,0, PEN_EXCLUSIVE|PEN_NO_SETCOLOR);
  1401.  
  1402.         if(Pen[n] == -1)
  1403.         {
  1404.             ReleaseColours();
  1405.             return(FALSE);
  1406.         }
  1407.     }
  1408.  
  1409.     for(n = 0 ; n < 8 ; n++)
  1410.     {
  1411.         SetColour(n + 16,colormap[n + 16].red,colormap[n + 16].green,colormap[n + 16].blue);    // clut 2
  1412.         SetColour(n + 24,colormap[n + 24].red,colormap[n + 24].green,colormap[n + 24].blue);    // clut 3
  1413.     }
  1414.  
  1415.     for(n = 0 ; n < 4 ; n++)    // dclut
  1416.         SetColour(32 + n,colormap[32 + n].red,colormap[32 + n].green,colormap[32 + n].blue);
  1417.  
  1418.     for(n = 0 ; n < 24 ; n++)
  1419.         SetColour(32 + 4 + n,colormap[32 + 4 + n].red,colormap[32 + 4 + n].green,colormap[32 + 4 + n].blue);
  1420.  
  1421.     return(TRUE);
  1422. }
  1423.